
<template>
  <div :id="'player'+params.id" class="play-box" :class="{'column':type==='column'}" @click="clickScreen()" @dblclick="fullsrceen()">
    <div class="theplay" :id="params.id"></div>
    <div class="logo" v-if="!playState">
      <img src="/static/image/logo1.png" alt="" />
    </div>
  </div>
</template>
<style lang="scss">
  .play-box{
    position: relative;
    display: inline-block;
    flex-shrink: 0;
    flex-grow: 0;
    &.column{
      flex-shrink: 1;
      flex-grow: 1;
    }
    .theplay {
      width: 100%;
      height: 100%;
      background: black;
    }
    .logo {
      position: absolute;
      top: 0;
      left: 0;
      // width: 100%;
      // height: 100%;
      width: calc(100% - 1px);
      height: calc(100% - 1px);
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 100;
      background: black;
    }
    .logo img {
      width: 20%;
      height: auto;
    }
  }
// 播放器底部控制栏按钮样式
.jessibuca-container{
  .jessibuca-controls{
    padding: 0 5px;
    .jessibuca-controls-bottom{
      position: relative;
      .jessibuca-controls-left {
        white-space: nowrap;
        .jessibuca-controls-item {
          padding: 0 5px 0 0;
        }
      }
      .jessibuca-controls-right{
        // display: none;
        flex-wrap: wrap;
        background: #161616;
        position: absolute;
        top: 0;
        right: 0;
        height: 100%;
        justify-content: flex-end;
        .jessibuca-controls-item {
          padding: 0 5px;
        }
      }
    }
  }
  &:hover{
    .jessibuca-controls .jessibuca-controls-bottom .jessibuca-controls-right{
      display: flex;
    }
  }
}
</style>
<script>
export default {
  name: "child-play",
  props:{
    /**
     * ------------state=0停止，1播放，2暂停;isKeyPlay是否是关键帧播放
     * id: this.randomStr(8),hadUsed: false,hide: false,state: 0,,isKeyPlay: falseterminal: "",terminalId: "",channel: 1,name: "",streamType: 0,
     * ------------progress:当前回放进度(秒),totalTime:总回放时间(秒)
     * ------------speed:25(慢进4倍),50(慢进2倍),100(正常),200(快进2倍),400(快进4倍)
     * ------------isDevice播放器要播放的是不是设备类型的视频
     * ------------offsetTime设备类型视频拖动后要记录一个偏移值
     * isDevice:true,offsetTime:0,volume:10,mute:false,progress:100,totalTime:100,speed:100,startTime:"",endTime:"" //主要是在录像回放里面使用
     * realPlay: true//true直播,false回放(包含设备类视频和服务器类视频)
     * playType: "",dGbId: "",gbId: ""
     * ------------playType=1是28181哪里的播放服务器地址，后台直接返回完整的播放地址，不需要拼接;=""播放地址需要从播放参数那里用参数拼接;
     * ------------dGbId、dGbId当playType==1的时候需要用到这两个字段(此时的terminal用不到了)
     * showCarBtn: false//是否显示全车图标的控制按钮---轮播的时候用到
     * recording: false//是否正在录像中---可用可不用--一般是外部调用录像的时候用到
     * streamid  流id
     */
    params:{
      type: Object,
      default:()=>{
        return {}//id: this.randomStr(8),hadUsed: false未使用的窗口只有这两个属性
      }
    },
    type: {
      type: String,
      default: "box"//column
    }
  },
  data() {
    return {
      playUI: null,
      currentPlayerTime: 0,//播放器当前的时间戳
      style: {},
      playUrl: "",
      playState: 0,//0停止，1播放，2暂停
      toReSendApiTime: 5,//播放器没流n秒后重新发送播放请求
      reloadingMax: 5,//播放器连续拉流次数，超过后不再重复请求接口拉流了。如果来流了，就重新恢复5次
      resendSTO: null,//重新发送播放请求计时器
      recordName: "",//录像是保存到本地的文件名
      fullscreen: false,//是否全屏
    }
  },
  watch: {
    params:{
      handler(newD, oldD){
        // this.initData();
      },
      deep:true, // 必须加这个属性
      immediate: false, // 页面进来时触发一次
    },
  },
  beforeDestroy(){
    console.log("触发了销毁了")
    if(this.resendSTO){
      clearTimeout(this.resendSTO);
      this.resendSTO = null;
    }
    if(this.params.hadUsed&&!!this.playUI){
      this.playUI.destroy();
      this.playUI = null;
      if(this.params.isDevice){
        this.$emit("eventListener",{
          id: this.params.id,
          terminalId:this.params.terminalId,
          channel:this.params.channel,
          realPlay: this.params.realPlay,
          type:'destroy'
        });
      }
    }
  },
  activated(){//使用了keep-alive才会触发
    let that = this;
    if(!!this.playUrl&&!!that.playUI&&this.playState==1){//因为路由切换离开时视频会自动进入暂停状态，这里需要恢复成播放状态
      this.recoveryPlayVideoH5();
    }
  },
  methods: {
    initPlayer(){//初始化播放器
      let that = this;
      that.reloadingMax = 5;
      that.fullscreen = false;
      /*global JessibucaPro*/
      /*eslint no-undef: "error"*/
      if(that.params.realPlay){//直播
        function startRecord(){
          that.recordName = that.params.name+'_'+that.params.channel+'_'+that.formatTime(new Date(),"yyyy-MM-dd HH:mm:ss");
          that.playUI.startRecord();
        }
        function stopRecord(){
          that.playUI.stopRecordAndSave('download',that.recordName+'至'+that.formatTime(new Date(),"yyyy-MM-dd HH:mm:ss"));
          that.recordName = '';
        }
        that.playUI = new JessibucaPro({
          container: document.getElementById(that.params.id),
          decoder: "/static/jessibuca/decoder-pro.js",
          useMSE: true, //mse硬解码
          useVideoRender: true,
          wasmUseVideoRender: true,
          autoWasm: true,
          videoBuffer: 0.2, // 缓存时长
          videoBufferDelay: 1,
          // supportDblclickFullscreen: true,//是否支持屏幕的双击事件，触发全屏，取消全屏事件
          isFlv: true,
          isResize: false,
          text: "",
          loadingIcon: false,
          controlAutoHide: false,//鼠标聚焦到播放器内部会显示操作栏
          loadingText: "",
          recordType: "mp4",//视频录制默认的格式，支持webm和mp4。
          debug: false,
          audioEngine: "worklet",
          showBandwidth: true, // 显示网速
          operateBtns: {
            fullscreen: true,
            screenshot: true,
            // performance: true,//性能面板开启
            play: true,
            audio: true,
            record: true,
            recordFn: startRecord,
            recordStopFn: stopRecord,
            close: true
          },
          watermarkConfig:{
            opacity: 0,
            text: {
              content: '',
              fontSize: '0',
              color: '#000'
            },
          },
          isNotMute: true
        });
        that.playUI.on('close', () => {
          setTimeout(() => {//点击停止按钮
            if(that.params.hadUsed&&!!that.playUrl){
              that.playState = 0;
              console.log("点点击停止按钮playState==",that.playState);
              that.$emit("eventListener",{id:that.params.id,type:'stop',realPlay:that.params.realPlay});
            }
          }, 10);
        });
      }else{//回放
        let option = {
          container: document.getElementById(that.params.id),
          videoBuffer: 0.2, // 缓存时长
          videoBufferDelay: 3,//设置最大缓冲延迟时长，单位秒，如果延迟超过该值，就会进行丢帧处理。
          loadingTimeout: 10,
          loadingTimeoutReplayTimes: -1,
          heartTimeout: 5*10*60,//秒
          heartTimeoutReplay: false,
          heartTimeoutReplayTimes: -1,
          isResize: false,
          showBandwidth: true, // 显示网速
          // supportDblclickFullscreen: true,//是否支持屏幕的双击事件，触发全屏，取消全屏事件
          loadingIcon: false,
          recordType: "mp4",//视频录制默认的格式，支持webm和mp4。
          operateBtns: {
            performance: true,//性能面板开启
            recordStopFn: function(){
              that.$emit("eventListener",{id:that.params.id,type:'record',bool: false,realPlay:that.params.realPlay});
            },
          },
          playbackConfig: {
            showControl: false,//是否显示底部UI 24小时控制条
            fps: 15,
            isCacheBeforeDecodeForFpsRender: true,//是否在解码前缓存数据
            isUseFpsRender: true,//是否使用固定的fps渲染，如果设置的fps小于流推过来的，会造成内存堆积甚至溢出
          },
          isNotMute: true
        };
        if(that.params.isDevice){//设备类视频
          Object.assign(option,{
            decoder: "/static/jessibuca/decoder-pro.js",
            isLive: true,//是否是直播，默认true
            useMSE: true,
            useVideoRender: true,
            wasmUseVideoRender: true,
            autoWasm: true,
            isFlv: true,
          });
          that.playUI = new JessibucaPro(option);
        }else{//服务器类视频
          Object.assign(option,{
            isLive: false,//是否是直播
            useMSE: false,
            isFlv: false,
          });
          that.playUI = new JessibucaPro(option);
          setTimeout(() => {
            that.playUI.$videoElement.controls = false;
          }, 0);
          that.playUI.$videoElement.addEventListener("timeupdate",function(){
            if(that.playUI.$videoElement){
              let time = parseInt(that.playUI.$videoElement.currentTime);
              // console.log('当前播放器时间===', time);//拖动进度条的时候time不会归零
              if(that.playState==1&&time>that.currentPlayerTime){
                that.currentPlayerTime = time;
                that.$emit("eventListener",{
                  id: that.params.id,
                  type:'timeUpdate',
                  time: time,
                  realPlay:that.params.realPlay
                });
              }
            }
          },false);
        }
      }
      if(that.params.isDevice){//设备类
        that.playUI.onPause = () => {//点击暂停按钮
          that.playState = 2;
          console.log("点击暂停按钮playState==",that.playState);
          that.pauseVideoH5();
        };
        that.playUI.onPlay = () => {//点击播放按钮
          if(that.params.hadUsed&&!!that.playUrl){
            that.playState = 1;
            console.log("点击播放按钮playState==",that.playState);
            that.recoveryPlayVideoH5();
          }
        };
        let destoying = false;
        that.playUI.on("error", function (error) {
          console.log("playState==error",that.playState,error);
          if(!destoying){
            destoying = true;
            that.playUI.destroy();
            that.$emit("eventListener",{id:that.params.id,type:'stop',realPlay:that.params.realPlay});
            that.initPlayer();
          }
        });
        let fps = 0;
        that.playUI.on(that.params.realPlay?'stats':'playbackStats', function (stats) {
          if(that.playState==1){//播放中
            // console.log("fps: 当前视频帧率===="+that.params.channel,stats.fps);
            // console.log("====",stats);
            // console.log(that.params.channel+"--stats.pTs===="+stats.pTs,"that.params.progress====="+(that.params.progress-that.params.offsetTime))
            if(!!stats.fps){//有流了
              if(that.resendSTO){
                clearTimeout(that.resendSTO);
                that.resendSTO = null;
              }
            }else if(!that.resendSTO&&!fps){//播放器没流n秒后重新发送播放请求
              that.resendSTO = setTimeout(function(){
                if(that.playState==1){
                  // console.log(that.params.channel+"----最大拉流次数剩余====="+that.reloadingMax)
                  if(that.reloadingMax>0){
                    that.$emit("eventListener",{id:that.params.id,type:'resendAPI',realPlay:that.params.realPlay});
                    that.reloadingMax--;
                  }else{//that.reloadingMax*that.toReSendApiTime后重新从这个时间点开始播放
                    that.$emit("eventListener",{id:that.params.id,type:'stop',realPlay:that.params.realPlay,needReplay:true});
                  }
                }
                that.resendSTO = null;
              },that.toReSendApiTime*1000);
            }
            fps = stats.fps;
            if(!that.params.realPlay&&that.playState==1){
              let time = parseInt(stats.ts/1000);
              // console.log('当前播放器时间==='+that.params.channel,time,that.params.progress);//拖动进度条的时候time会归零
              if(time<that.params.progress+100){//过滤掉突然间的大数值
                that.$emit("eventListener",{
                  id: that.params.id,
                  type:'timeUpdate',
                  time: time,
                  realPlay:that.params.realPlay
                });
              }
            }
          }
        });
      }
    },
    recoveryPlayVideoH5(){//恢复播放
      this.currentPlayerTime = 0;
      if(!!this.playUI&&!!this.playUrl){
        if(this.params.realPlay){//直播
          this.playUI.play();
        }else if(this.params.isDevice){//设备类回放
          this.playUI.playbackResume();
        }else{//服务器类回放
          this.playUI.$videoElement.play();
        }
        this.playState = 1;
        this.toReSendApiTime = 5;
      }
    },
    specifyPlayVideoH5(playUrl){//指定视频窗口播放
      // console.log("指定视频窗口播放",playUrl,this.params);
      if(!playUrl){
        this.$message.warning("播放地址为空，无法播放！");
        return;
      }
      this.playUrl = playUrl;
      let that = this;
      setTimeout(function () {
        if(that.params.name){
          that.initPlayer();
          that.playUI.play(playUrl);
          that.playState = 1;
          if ($("#player"+that.params.id+" .jessibuca-controls-left").find(".theChannel")) {
            $("#player"+that.params.id+" .jessibuca-controls-left").find(".theChannel").remove();
          }
          let deviceHtml =`<div class="jessibuca-controls-item theChannel">${that.params.name}_${that.params.channel}</div>`;
          $("#player"+that.params.id+" .jessibuca-controls-bottom").find(".jessibuca-controls-left").prepend(deviceHtml);
        }else{
          that.$emit("eventListener",{id:that.params.id,type:'stop',realPlay:that.params.realPlay});
        }
      }, 1000);
    },
    specifyPlaybackVideoH5(playUrl){//指定视频窗口播放
      console.log("指定视频窗口回放",playUrl);
      if(!playUrl){
        this.$message.warning("播放地址为空，无法播放！");
        return;
      }
      this.playUrl = playUrl;
      let that = this;
      setTimeout(function () {
        that.currentPlayerTime = 0;
        that.playState = 1;
        that.initPlayer();
        if(that.params.isDevice){//设备类
          that.playUI.playback(playUrl,{
            showControl: false,//是否显示底部UI 24小时控制条
            fps: 15,
            isCacheBeforeDecodeForFpsRender: true,//是否在解码前缓存数据
            isUseFpsRender: true,//是否使用固定的fps渲染，如果设置的fps小于流推过来的，会造成内存堆积甚至溢出
          });
          if ($("#player"+that.params.id+" .jessibuca-controls-left").find(".theChannel")) {
            $("#player"+that.params.id+" .jessibuca-controls-left").find(".theChannel").remove();
          }
          let str = that.params.startTime.split(" ")[1]+"~"+that.params.endTime.split(" ")[1];
          let deviceHtml =`<div class="jessibuca-controls-item theChannel">${that.params.name}_${that.params.channel}(${str})</div>`;
          $("#player"+that.params.id+" .jessibuca-controls-bottom").find(".jessibuca-controls-left").prepend(deviceHtml);
        }else{//服务器类
          that.playUI.play(playUrl);
          if(that.params.progress){//为了兼容echarts时间戳播放
            that.gragePlaybackVideo();
          }
        }
      }, 1000);
    },
    gragePlaybackVideo(){//拖动播放
      if(!this.params.isDevice){
        this.playUI.$videoElement.currentTime = Number(this.params.progress);
      }
    },
    clearCacheBufferOfBack(){//清除缓存的数据，用于seek之后，清除之前的数据。
      this.playUI.playbackClearCacheBuffer();
    },
    speedChangePlay(rate){//回放慢进快进
      if(this.params.isDevice){
        if(rate!=1){
          this.playUI.forward(rate);
        }else{//恢复正常
          this.playUI.normal();
        }
      }else{
        this.playUI.$videoElement.playbackRate = rate;
      }
    },
    closePlayH5(){//关闭指定播放
      console.log("关闭指定播放",this.params.id);
      if(!!this.playUI)this.playUI.destroy();
      this.playState = 0;
      if(this.resendSTO){
        clearTimeout(this.resendSTO);
        this.resendSTO = null;
      }
      this.playUrl = '';
    },
    sendApiAndreplayVideo(){//播放器断流太久，重新发送播放请求并且播放
      this.toReSendApiTime = 8;
      this.currentPlayerTime = 0;
      this.playState = 1;
      this.toReSendApiTime = 5;
      // this.recoveryPlayVideoH5();
    },
    flv_screenshotH5(){//截图拍照
      if(this.params.isDevice){
        var time = parseInt((new Date(this.params.startTime).getTime())/1000) + parseInt(this.params.progress);
        this.playUI.screenshot(this.params.name+'_'+this.params.channel+this.formatTime(time*1000,"yyyy-MM-dd HH:mm:ss"));
      }else{
        var video = this.playUI.$videoElement;
        var scale = 1;
        var canvas = document.createElement("canvas");
        canvas.width = video.videoWidth * scale;
        canvas.height = video.videoHeight * scale;
        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
        var img = document.createElement("img");
        img.crossOrigin = 'anonymous';
        img.src = canvas.toDataURL("image/png");
        //$output.prepend(img);
        var image = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream');
        var time = parseInt((new Date(this.params.startTime).getTime())/1000) + parseInt(video.currentTime);
        if(!!this.params.offsetTime){
          time = time + parseInt(this.params.offsetTime);
        }
        this.toDownLoadImg(image,this.params.name+'_'+this.params.channel+this.formatTime(time*1000,"yyyy-MM-dd HH:mm:ss")+'.png');
      }
    },
    pauseVideoH5(){//暂停
      this.playState = 2;
      if(this.params.realPlay){//直播
        this.playUI.pause();
      }else if(this.params.isDevice){//设备类
        this.playUI.playbackPause();
      }else{//服务器类回放
        this.playUI.$videoElement.pause();
      }
    },
    setVideoVolumeH5(num){//设置音量0-1
      if(this.params.realPlay||this.params.isDevice){//直播||设备类回放
        if(num===0){
          this.playUI.mute();
        }else{
          this.playUI.cancelMute();
          this.playUI.setVolume(num);
        }
      }else{//服务器类回放
        if(num===0){
          this.playUI.$videoElement.muted = true;
        }else{
          this.playUI.$videoElement.muted = false;
          this.playUI.$videoElement.volume = num;
        }
      }
    },
    recordVideo(type){//录像，true是录像，false是停止录像
      if(this.params.isDevice){//设备类
        if(type){
          var time = parseInt((new Date(this.params.startTime).getTime())/1000) + parseInt(this.params.progress);
          this.recordName = this.params.name+'_'+this.params.channel+'_'+this.formatTime(time*1000,"yyyy-MM-dd HH:mm:ss");
          this.playUI.startRecord();
        }else{
          this.playUI.stopRecordAndSave('download',this.recordName+'至'+this.formatTime(new Date(),"yyyy-MM-dd HH:mm:ss"));
          this.recordName = '';
        }
      }
    },
    clickScreen(){//点击了窗口
      this.$emit("eventListener",{id:this.params.id,type:'click'});
    },
    fullsrceen(){//全屏非全屏
      if(this.params.hadUsed&&!!this.playState){
        this.playUI.setFullscreen(!this.fullscreen);
        this.fullscreen = !this.fullscreen;
      }
    }
  }
};
</script>

